//*********************************************************************
//		Copyright (c) 2003 - 2008 Microsoft Corporation.
//      This code is provided under Microsoft Public License, which can be found at
//      http://www.microsoft.com/resources/sharedsource/licensingbasics/publiclicense.mspx 
//
// @File: Collector_WMI.cs
//
// Purpose: Collector for data accessed through WMI
//
//
//
// Notes: 
//
//
//	
// History: 
//     @Version: V2.1
//
//     07/14/08 PGV 2.1.001.0 Starting V2.1 (based on 2.0.030.0 code)
//     10/14/08 PGV 2.1.002.0 Fix for product.version = NULL
//
//
// @EndHeader@
//*********************************************************************

using System;
using System.Management;
using System.Data;
using System.Data.SqlClient;
using Microsoft.Win32;
using System.Diagnostics;
using System.Collections;

using H2V2;

namespace H2V2.Collector
{
    enum WmiClassType
    {
        OperatingSystem = 1,
        Hotfix,
        NetworkAdapter,
        NetworkAdapterConfiguration,
        DiskDrive,
        DiskPartition,
        LogicalDisk,
        ComputerSystem,
        EventLogFile,
        Processor,
        Process,
        Product,
        Service
    }

    class WmiClass 
	{
		public string wmiClass;
        public WmiClassType storeType;

        public WmiClass (string a_class, WmiClassType a_type)
		{
			wmiClass = a_class;
			storeType = a_type;
		}
	}

    class RegistryHotfix : RegistryBaseKey
    {
        public string Component;
        public string ServicePack;
        public string HotFixID;
        public string Description;
        public string FixComments;
        public DateTime InstalledDate;
        public string InstalledBy;
    }

    public class CollectorWmi : CollectorBase
	{
		static int ms_collectorID = 0;

        public override string Version { get { return "2.2.001.0"; } }
		public override string Name { get { return "WMI"; } }

		ArrayList wmiClassArray;
		ArrayList historyProcArray;

		public CollectorWmi(string a_machine_name, RunDescriptor a_rd)
			: base (a_machine_name, a_machine_name, a_rd)
		{
			// default collector mask is 0x7fffffff
			// 0x1 - OS/CS; 0x2 - QFE; 0x4 - NIC; 0x8 - Disk; 0x10 - EventLogFile; 
			// 0x20 - Processes; 0x40 - Products; 0x80 - Services
			m_track_id = 1;

			wmiClassArray = new ArrayList (4);
			historyProcArray = new ArrayList (4);
		}

		public override void Init (Connection a_repository) 
		{
			m_track_id = 10;
			base.Init (a_repository);

			m_track_id = 11;
			if (ms_collectorID == 0)
			{
				ms_collectorID = RegisterCollector ();
			}
			m_collectorID = ms_collectorID;
			m_track_id = 12;
		}

		public override void Collect ()
		{
			m_track_id = 1000;
			ChangeStatus ("Running WMI collector");
			try
			{
				m_track_base = 1000;
				UnitCollectOSCS ();
				m_track_base = 1100;
				UnitCollectNIC ();
				m_track_base = 1200;
				UnitCollectDiskDrive ();
				m_track_base = 1300;
				UnitCollectHotfix ();
				m_track_base = 1400;
				UnitCollectLogFile ();
				m_track_base = 1500;
				UnitCollectProcess ();
				m_track_base = 1600;
				UnitCollectProduct ();
				m_track_base = 1700;
				UnitCollectService ();
			}
			catch (Exception ex)
			{
				ChangeStatus ("  "+ex.Message, StatusEventType.ERROR);
				ChangeStatus ("  WMI Collector encountered critical error. Abandoning Collector.", StatusEventType.WARNING);
                if (GlobalEnvironment.RepositoryFailure) 
				{
					throw;
				}
				else
				{
					LogMgrError (RunErrorClass.Wmi, m_CurrentUnit, ex.GetType ().Name, 0, 0, ex.Message); 
				}
			}
		}

		#region Unit Collection functions

		void CollectUnit (int a_unit, string a_comment)
		{
			int step = 10;

			m_track_id = m_track_base + 1;
			UnitOpen (a_unit, a_comment);

			try 
			{
				foreach (WmiClass wmiClass in wmiClassArray)
				{
					m_track_id = m_track_base + step;
					CollectWmiClass (wmiClass.wmiClass, wmiClass.storeType);
					step += 10;
				}

				foreach (string hProc in historyProcArray)
				{
					m_track_id = m_track_base + step;
					CallHistoryProc (hProc);
					step += 10;
				}

				m_track_id = m_track_base + 90;
				UnitSaveData ();
			}
			catch (CollectorErrorException cerr)
			{
                if (cerr.m_Error == CollectorError.WmiInvalidClass || cerr.m_Error == CollectorError.WmiProviderLoadFailure) 
				{
					LogMgrError (RunErrorClass.Wmi, m_CurrentUnit, cerr.GetType ().Name, cerr.m_Error, 0, cerr.Message); 
					ChangeStatus ("Unit "+a_unit+" failed", StatusEventType.ERROR);
				}
				else
				{
					throw;
				}
			}
			finally
			{
				++m_track_id;
				UnitClose ();
			}
		}

		void UnitCollectOSCS ()
		{
			if ((m_options & 0x1) > 0) 
			{
				wmiClassArray.Clear ();
				wmiClassArray.Add (new WmiClass ("Win32_OperatingSystem", WmiClassType.OperatingSystem ));
				wmiClassArray.Add (new WmiClass ("Win32_ComputerSystem", WmiClassType.ComputerSystem));
				wmiClassArray.Add (new WmiClass ("Win32_Processor", WmiClassType.Processor));

				historyProcArray.Clear ();

				CollectUnit (1, "OS/CS");
			}
		}

		void UnitCollectNIC ()
		{
			if ((m_options & 0x4) > 0) 
			{
				wmiClassArray.Clear ();
				wmiClassArray.Add (new WmiClass ("Win32_NetworkAdapter", WmiClassType.NetworkAdapter));
				wmiClassArray.Add (new WmiClass ("Win32_NetworkAdapterConfiguration", WmiClassType.NetworkAdapterConfiguration));

				historyProcArray.Clear ();
				historyProcArray.Add ("sph_NIC");
				historyProcArray.Add ("sph_NICconfig");

				CollectUnit (2, "NIC");
			}
		}

		void UnitCollectDiskDrive ()
		{
			if ((m_options & 0x8) > 0) 
			{
				wmiClassArray.Clear ();
				wmiClassArray.Add (new WmiClass ("Win32_DiskDrive", WmiClassType.DiskDrive));
                wmiClassArray.Add (new WmiClass ("Win32_DiskPartition", WmiClassType.DiskPartition));
                wmiClassArray.Add (new WmiClass ("Win32_LogicalDisk", WmiClassType.LogicalDisk));

				historyProcArray.Clear ();
				historyProcArray.Add ("sph_DiskDrive");
                historyProcArray.Add ("sph_DiskPartition");
                historyProcArray.Add ("sph_LogicalDisk");

				CollectUnit (3, "Disk");
			}
		}

		void UnitCollectHotfix ()
		{ // we don't use wmi to get hotfixes, so we don't use CollectUnit here
			if ((m_options & 0x2) > 0) 
			{
				m_track_id = m_track_base + 1;
				UnitOpen (4, "Hotfixes");
				m_track_id = m_track_base + 10;
				CollectHotfixRegistry ();
				m_track_id = m_track_base + 20;
				CallHistoryProc ("sph_qfe");
				m_track_id = m_track_base + 90;
				UnitSaveData ();
				++m_track_id;
				UnitClose ();
			}
		}

		void UnitCollectLogFile ()
		{
			if ((m_options & 0x10) > 0) 
			{
				wmiClassArray.Clear ();
				wmiClassArray.Add (new WmiClass ("Win32_NTEventlogFile", WmiClassType.EventLogFile));

				historyProcArray.Clear ();

				CollectUnit (5, "EventLog files");
			}
		}

		void UnitCollectProcess ()
		{
			if ((m_options & 0x20) > 0) 
			{
				wmiClassArray.Clear ();
				wmiClassArray.Add (new WmiClass ("Win32_Process", WmiClassType.Process));

				historyProcArray.Clear ();
				historyProcArray.Add ("sph_task");

				CollectUnit (6, "Processes");
			}
		}

		void UnitCollectProduct ()
		{
			if ((m_options & 0x40) > 0) 
			{
				wmiClassArray.Clear ();
				wmiClassArray.Add (new WmiClass ("Win32_Product", WmiClassType.Product));

				historyProcArray.Clear ();
				historyProcArray.Add ("sph_product");

				CollectUnit (7, "Products");
			}
		}

		void UnitCollectService ()
		{
			if ((m_options & 0x80) > 0) 
			{
				wmiClassArray.Clear ();
				wmiClassArray.Add (new WmiClass ("Win32_Service", WmiClassType.Service));

				historyProcArray.Clear ();
				historyProcArray.Add ("sph_service");

				CollectUnit (8, "Services");
			}
		}
		
		#endregion

		static bool IsNotFound (string msg)
		{
			return (msg.StartsWith ("Not found"));
		}

		static DateTime MakeDate (string inDate)
		{
            DateTime dt = MIN_DATE;

            if (String.IsNullOrEmpty (inDate))
            {
                return MIN_DATE;
            }

			int yr = Convert.ToInt32 (inDate.Substring(0,4));
			int mo = Convert.ToInt32 (inDate.Substring(4,2));
			int dy = Convert.ToInt32 (inDate.Substring(6,2));

            if (inDate.Length > 8)
            {
                int hr = Convert.ToInt32 (inDate.Substring (8, 2));
                int mn = Convert.ToInt32 (inDate.Substring (10, 2));
                int sc = Convert.ToInt32 (inDate.Substring (12, 2));

                dt = new DateTime (yr, mo, dy, hr, mn, sc);
            }
            else
            {
                dt = new DateTime (yr, mo, dy);
            }
			return dt;
		}

		#region Collection Functions 

        void CollectWmiClass (string a_class, WmiClassType a_type)
		{
			ChangeStatus("  Collecting "+a_class);
			string scope = "\\\\"+m_inst_name+"\\root\\cimv2";
			string query = "SELECT * FROM "+a_class;

			UnitUpdateStatus (m_track_id);
			CollectWmi (scope, query, (uint)a_type);
		}

		void CollectHotfixRegistry ()
		{
			RegistryKey rk,
				srk;

			ChangeStatus ("  Collecting Hotfix Registry");

			UnitUpdateStatus (m_track_id);
			rk = RegistryKey.OpenRemoteBaseKey (RegistryHive.LocalMachine, m_machine_name);
			rk = rk.OpenSubKey ("SOFTWARE\\Microsoft\\Updates");
			if (rk == null) return;  // There is no subkey

			foreach (string skey in rk.GetSubKeyNames ())
			{
				RegistryHotfix rqfe = new RegistryHotfix ();
				rqfe.Component = skey;
				rqfe.Key = skey;

				srk = rk.OpenSubKey (skey);
				rqfe.Name = srk.Name;

				collect_Registry (srk, 2, (RegistryBaseKey)rqfe, skey);
			}
		}

		#endregion

		#region Store Functions
		protected override void StoreWmi (uint a_type, ManagementObject a_mo)
		{
            WmiClassType wmt = (WmiClassType)a_type;

			switch (wmt)
			{
				case WmiClassType.OperatingSystem:
					StoreOS (a_mo);
					break;
                case WmiClassType.Hotfix:
                    // reserved for Hotfixes, which is handled as a special case directly through Registry
                    break;
				case WmiClassType.NetworkAdapter:
					StoreNIC (a_mo);
					break;
				case WmiClassType.NetworkAdapterConfiguration:
					StoreNicConfig (a_mo);
					break;
				case WmiClassType.DiskDrive:
					StoreDiskDrive (a_mo);
					break;
				case WmiClassType.DiskPartition:
					StoreDiskPartition (a_mo);
					break;
				case WmiClassType.LogicalDisk:
					StoreLogicalDisk (a_mo);
					break;
				case WmiClassType.ComputerSystem:
					StoreCS (a_mo);
					break;
				case WmiClassType.EventLogFile:
					StoreLogFileInfo (a_mo);
					break;
				case WmiClassType.Processor:
					StoreProcessor (a_mo);
					break;
				case WmiClassType.Process:
					StoreProcess (a_mo);
					break;
				case WmiClassType.Product:
					StoreProduct (a_mo);
					break;
				case WmiClassType.Service:
					StoreService (a_mo);
					break;
			}
		}

        void StoreOS (ManagementObject a_mo)
        {
            int ps = -1,
                NumberOfUsers = -1,
                Locale = 0;
            bool debug = false,
                distrib = false,
                PAE = false;
            string BootDevice = "-",
                SystemDevice = "-";
            DateTime InstallDate,
                LastBoot,
                LocalTime;

            try
            {
                ps = (int)(uint)a_mo["OSProductSuite"];
            }
            catch (NullReferenceException) { /*Not implemented on all platforms*/}
            catch (ManagementException mngex)
            {
                if (!IsNotFound (mngex.Message)) throw mngex;
            }

            debug = (bool)a_mo["Debug"];
            distrib = (bool)a_mo["Distributed"];

            try
            {
                PAE = (bool)a_mo["PAEEnabled"];
            }
            catch (NullReferenceException) { /*Not implemented on all platforms*/}
            catch (ManagementException mngex)
            {
                if (!IsNotFound (mngex.Message)) throw mngex;
            }


            InstallDate = MakeDate ((string)a_mo["InstallDate"]);
            LastBoot = MakeDate ((string)a_mo["LastBootUpTime"]);
            LocalTime = MakeDate ((string)a_mo["LocalDateTime"]);

            try
            {
                NumberOfUsers = (int)(uint)a_mo["NumberOfUsers"];
                BootDevice = (string)a_mo["BootDevice"];
                SystemDevice = (string)a_mo["SystemDevice"];
            }
            catch { }

            Locale = short.Parse ((string)a_mo["Locale"]);

            SqlCommand sqlcmd = new SqlCommand ();
            sqlcmd.CommandText =
@"Insert dbo.c_wmi_OS (run_id,srv_id,BootDevice,BuildNumber,BuildType,Caption,CodeSet,CountryCode,
CSDVersion,CSName,CurrentTimeZone,Debug,Distrib,FreePhysicalMemory,FreeSpaceInPagingFiles,FreeVirtualMemory,
InstallDate,LastBootUpTime,LocalDateTime,Locale,MaxProcessMemorySize,
NumberOfProcesses,NumberOfUsers,OSLanguage,OSProductSuite,PAEEnabled,
ServicePackMajorVersion,ServicePackMinorVersion,SizeStoredInPagingFiles,
SystemDevice,SystemDirectory,TotalVirtualMemorySize,TotalVisibleMemorySize,Version,WindowsDirectory) 
Values (@run_id,@srv_id,@BootDevice,@BuildNumber,@BuildType,@Caption,@CodeSet,@CountryCode,
@CSDVersion,@CSName,@CurrentTimeZone,@Debug,@Distrib,@FreePhysicalMemory,@FreeSpaceInPagingFiles,@FreeVirtualMemory,
@InstallDate,@LastBootUpTime,@LocalDateTime,@Locale,@MaxProcessMemorySize,
@NumberOfProcesses,@NumberOfUsers,@OSLanguage,@OSProductSuite,@PAEEnabled,
@ServicePackMajorVersion,@ServicePackMinorVersion,@SizeStoredInPagingFiles,
@SystemDevice,@SystemDirectory,@TotalVirtualMemorySize,@TotalVisibleMemorySize,@Version,@WindowsDirectory) ";
            sqlcmd.Parameters.AddWithValue ("@run_id", m_rd.run_id);
            sqlcmd.Parameters.AddWithValue ("@srv_id", m_rd.srv_id);
            sqlcmd.Parameters.AddWithValue ("@BootDevice", BootDevice);
            sqlcmd.Parameters.AddWithValue ("@BuildNumber", (string)a_mo["BuildNumber"]);
            sqlcmd.Parameters.AddWithValue ("@BuildType", (string)a_mo["BuildType"]);
            sqlcmd.Parameters.AddWithValue ("@Caption", (string)a_mo["Caption"]);
            sqlcmd.Parameters.AddWithValue ("@CodeSet", (string)a_mo["CodeSet"]);
            sqlcmd.Parameters.AddWithValue ("@CountryCode", (string)a_mo["CountryCode"]);
            sqlcmd.Parameters.AddWithValue("@CSDVersion", (a_mo["CSDVersion"] == null ? "RTM" : (string)a_mo["CSDVersion"]));
            sqlcmd.Parameters.AddWithValue ("@CSName", (string)a_mo["CSName"]);
            sqlcmd.Parameters.AddWithValue ("@CurrentTimeZone", (short)a_mo["CurrentTimeZone"]);
            sqlcmd.Parameters.AddWithValue ("@Debug", debug);
            sqlcmd.Parameters.AddWithValue ("@Distrib", distrib);
            sqlcmd.Parameters.AddWithValue ("@FreePhysicalMemory", (long)(ulong)a_mo["FreePhysicalMemory"]);
            sqlcmd.Parameters.AddWithValue ("@FreeSpaceInPagingFiles", (long)(ulong)a_mo["FreeSpaceInPagingFiles"]);
            sqlcmd.Parameters.AddWithValue ("@FreeVirtualMemory", (long)(ulong)a_mo["FreeVirtualMemory"]);
            sqlcmd.Parameters.AddWithValue ("@InstallDate", InstallDate);
            sqlcmd.Parameters.AddWithValue ("@LastBootUpTime", LastBoot);
            sqlcmd.Parameters.AddWithValue ("@LocalDateTime", LocalTime);
            sqlcmd.Parameters.AddWithValue ("@Locale", Locale);
            sqlcmd.Parameters.AddWithValue ("@MaxProcessMemorySize", (long)(ulong)a_mo["MaxProcessMemorySize"]);
            sqlcmd.Parameters.AddWithValue ("@NumberOfProcesses", (int)(uint)a_mo["NumberOfProcesses"]);
            sqlcmd.Parameters.AddWithValue ("@NumberOfUsers", (int)(uint)NumberOfUsers);
            sqlcmd.Parameters.AddWithValue ("@OSLanguage", (int)(uint)a_mo["OSLanguage"]);
            sqlcmd.Parameters.AddWithValue ("@OSProductSuite", ps);
            sqlcmd.Parameters.AddWithValue ("@PAEEnabled", PAE);
            sqlcmd.Parameters.AddWithValue ("@ServicePackMajorVersion", (short)(ushort)a_mo["ServicePackMajorVersion"]);
            sqlcmd.Parameters.AddWithValue ("@ServicePackMinorVersion", (short)(ushort)a_mo["ServicePackMinorVersion"]);
            sqlcmd.Parameters.AddWithValue ("@SizeStoredInPagingFiles", (long)(ulong)a_mo["SizeStoredInPagingFiles"]);
            sqlcmd.Parameters.AddWithValue ("@SystemDevice", SystemDevice);
            sqlcmd.Parameters.AddWithValue ("@SystemDirectory", (string)a_mo["SystemDirectory"]);
            sqlcmd.Parameters.AddWithValue ("@TotalVirtualMemorySize", (long)(ulong)a_mo["TotalVirtualMemorySize"]);
            sqlcmd.Parameters.AddWithValue ("@TotalVisibleMemorySize", (long)(ulong)a_mo["TotalVisibleMemorySize"]);
            sqlcmd.Parameters.AddWithValue ("@Version", (string)a_mo["Version"]);
            sqlcmd.Parameters.AddWithValue ("@WindowsDirectory", (string)a_mo["WindowsDirectory"]);

            UnitAddData (sqlcmd);
        }

		void StoreCS (ManagementObject a_mo)
		{
			string s_Options = String.Empty,
				Manufacturer = String.Empty,
				Model = String.Empty;
			short Role;
			int Procs;
			long Mem;

			Role = (short)(ushort)a_mo["DomainRole"];
			try
			{
				Manufacturer = ((string)a_mo["Manufacturer"]).Trim ();
				Model = ((string)a_mo["Model"]).Trim ();
			}
            catch (NullReferenceException) { /*Not implemented on all platforms*/}
			Procs = (int)(uint)a_mo["NumberOfProcessors"];
			Mem = (long)(ulong)a_mo["TotalPhysicalMemory"];

            try
            {
                foreach (string s in (string[])a_mo["SystemStartupOptions"])
                {
                    s_Options += s;
                }
            }
            catch (NullReferenceException) { /*Not implemented on all platforms*/}

            SqlCommand sqlcmd = new SqlCommand ();
            sqlcmd.CommandText =
@"Insert dbo.c_wmi_CS (run_id,srv_id,DomainRole,Manufacturer,Model,NumberOfProcessors,SystemStartupOptions,TotalPhysicalMemory)
Values (@run_id,@srv_id,@DomainRole,@Manufacturer,@Model,@NumberOfProcessors,@SystemStartupOptions,@TotalPhysicalMemory) ";
            sqlcmd.Parameters.AddWithValue ("@run_id", m_rd.run_id);
            sqlcmd.Parameters.AddWithValue ("@srv_id", m_rd.srv_id);
            sqlcmd.Parameters.AddWithValue ("@DomainRole", Role);
            sqlcmd.Parameters.AddWithValue ("@Manufacturer", Manufacturer);
            sqlcmd.Parameters.AddWithValue ("@Model", Model);
            sqlcmd.Parameters.AddWithValue ("@NumberOfProcessors", Procs);
            sqlcmd.Parameters.AddWithValue ("@SystemStartupOptions", s_Options);
            sqlcmd.Parameters.AddWithValue ("@TotalPhysicalMemory", Mem);

			UnitAddData (sqlcmd);
		}

		void StoreProcessor (ManagementObject a_mo)
		{
			int L2CacheSize = 0,
				ExtClock = 0,
                ProcType = 0;

			try
			{
				L2CacheSize = (int)(uint)a_mo["L2CacheSize"];
			}
            catch (NullReferenceException) {/*Not implemented on all platforms*/}
			
            try
			{
				ExtClock = (int)(uint)a_mo["ExtClock"];
			}
            catch (NullReferenceException) {/*Not implemented on all platforms*/}
			
            try
			{
				object o = a_mo["ProcessorType"];
				if (o.GetType () == typeof (System.UInt16))
				{
					ProcType = (int)(ushort)o;
				}
				else
				{
					ProcType = (int)o;
				}
			}
            catch (NullReferenceException) {/*Not implemented on all platforms*/}

            SqlCommand sqlcmd = new SqlCommand ();
            sqlcmd.CommandType = CommandType.StoredProcedure;
            sqlcmd.CommandText = "dbo.spri_CPU";
            sqlcmd.Parameters.AddWithValue ("@run_id", m_rd.run_id);
            sqlcmd.Parameters.AddWithValue ("@srv_id", m_rd.srv_id);
            sqlcmd.Parameters.AddWithValue ("@Architecture", (int)(ushort)a_mo["Architecture"]);
            sqlcmd.Parameters.AddWithValue ("@CpuStatus", (int)(ushort)a_mo["CpuStatus"]);
            sqlcmd.Parameters.AddWithValue ("@CurrentClockSpeed", (int)(uint)a_mo["CurrentClockSpeed"]);
            sqlcmd.Parameters.AddWithValue ("@Descript", (string)a_mo["Description"]);
            sqlcmd.Parameters.AddWithValue ("@DeviceID", (string)a_mo["DeviceID"]);
            sqlcmd.Parameters.AddWithValue ("@ExtClock", ExtClock);
            sqlcmd.Parameters.AddWithValue ("@Family", (int)(ushort)a_mo["Family"]);
            sqlcmd.Parameters.AddWithValue ("@L2CacheSize", L2CacheSize);
            sqlcmd.Parameters.AddWithValue ("@Manufacturer", (string)a_mo["Manufacturer"]);
            sqlcmd.Parameters.AddWithValue ("@Name", (string)a_mo["Name"]);
            sqlcmd.Parameters.AddWithValue ("@ProcessorType", ProcType);

			UnitAddData (sqlcmd);
		}
	
		protected override void StoreRegistry (uint a_type, RegistryKey a_rk, RegistryBaseKey a_rb)
		{
			switch (a_type)
			{
				case 2:
					StoreHotfixRegistry (a_rk, a_rb);
					break;
				default:
					throw new CollectorErrorException (CollectorError.UnknownStoreType, 0, "Collector_WMI: unknown store type "+a_type);
			}
		}

		void StoreHotfixRegistry (RegistryKey a_rk, RegistryBaseKey a_rb)
		{
			string s,
				skey;

			RegistryHotfix rqfe = (RegistryHotfix)a_rb;

			skey = rqfe.Name.Substring (46);

			rqfe.HotFixID = rqfe.Key;
			rqfe.Description = (string)a_rk.GetValue ("Description");
			rqfe.FixComments = (string)a_rk.GetValue ("type");
			rqfe.InstalledBy = (string)a_rk.GetValue ("InstalledBy");

			s = (string)a_rk.GetValue ("InstalledDate");
			try
			{
				rqfe.InstalledDate = DateTime.Parse (s);
			}
			catch (ArgumentNullException) {}
			catch (FormatException) {}

			rqfe.ServicePack = rqfe.Node;

            SqlCommand sqlcmd = new SqlCommand ();
            sqlcmd.CommandType = CommandType.StoredProcedure;
            sqlcmd.CommandText = "dbo.spri_qfe";
            sqlcmd.Parameters.AddWithValue ("@run_id", m_rd.run_id);
            sqlcmd.Parameters.AddWithValue ("@srv_id", m_rd.srv_id);
            sqlcmd.Parameters.AddWithValue ("@component", rqfe.Component);
            sqlcmd.Parameters.AddWithValue ("@rkey", skey);
            sqlcmd.Parameters.AddWithValue ("@HotFixID", rqfe.HotFixID);
            if (rqfe.Description != null) sqlcmd.Parameters.AddWithValue ("@Description", rqfe.Description);
            if (rqfe.FixComments != null) sqlcmd.Parameters.AddWithValue ("@FixComments", rqfe.FixComments);
            if (rqfe.ServicePack != null) sqlcmd.Parameters.AddWithValue ("@ServicePack", rqfe.ServicePack);
            if (rqfe.InstalledDate != DateTime.MinValue) sqlcmd.Parameters.AddWithValue ("@InstalledDate", rqfe.InstalledDate);
            if (rqfe.InstalledBy != null) sqlcmd.Parameters.AddWithValue ("@InstalledBy", rqfe.InstalledBy);

			UnitAddData (sqlcmd);
		}

		void StoreNIC (ManagementObject a_mo)
		{
            short AdapterTypeID = -1;
			int	card_id = 0;
			string AdapterType = String.Empty,
                Manufacturer = String.Empty,
                ProductName = String.Empty,
                ServiceName = String.Empty,
                s_ResetTime;
            DateTime ResetTime;

			try
			{
				AdapterType = (string)a_mo["AdapterType"];
                if (AdapterType == null) AdapterType = String.Empty;
			}
			catch (NullReferenceException)
            {/*Not implemented on all platforms*/
			}
			catch (ManagementException mngex)
			{
                if (!IsNotFound (mngex.Message))
                {
                    throw mngex;
                }
			}

			try
			{
				AdapterTypeID = (short)(ushort)a_mo["AdapterTypeID"];
			}
			catch (NullReferenceException)
            {/*Not implemented on all platforms*/
			}
			catch (ManagementException mngex)
			{
                if (!IsNotFound (mngex.Message))
                {
                    throw mngex;
                }
            }

			if (AdapterTypeID == -1 && !String.IsNullOrEmpty (AdapterType))
			{
				AdapterTypeID = this.GetAdapterTypeID (AdapterType);
			}
            else if (AdapterTypeID == -1 && String.IsNullOrEmpty (AdapterType))
			{
				ProductName = (string)a_mo["ProductName"];
				ChangeStatus ("Unknown type; ProductName: "+ProductName, StatusEventType.DEBUG);
				return;
			}

			try
			{
				Manufacturer = (string)a_mo["Manufacturer"];
				ProductName = (string)a_mo["ProductName"];
				ServiceName = (string)a_mo["ServiceName"];
			}
            catch (NullReferenceException) {/*Not implemented on all platforms*/}
			// Card Registration is performed outside of Unit transaction
			// It affects dictionary only
			card_id = RegisterCard (ProductName, Manufacturer, ServiceName);

			s_ResetTime = (string)a_mo["TimeOfLastReset"];
			ResetTime = MakeDate (s_ResetTime);

            SqlCommand sqlcmd = new SqlCommand ();
            sqlcmd.CommandText =
@"Insert dbo.c_NIC (run_id,srv_id,card_id,AdapterTypeID,Availability,Idx,TimeOfLastReset) 
Values (@run_id,@srv_id,@card_id,@AdapterTypeID,@Availability,@Idx,@TimeOfLastReset) ";
            sqlcmd.Parameters.AddWithValue("@run_id", m_rd.run_id);
            sqlcmd.Parameters.AddWithValue("@srv_id", m_rd.srv_id);
            sqlcmd.Parameters.AddWithValue("@card_id", card_id);
            sqlcmd.Parameters.AddWithValue("@AdapterTypeID", AdapterTypeID);
            sqlcmd.Parameters.AddWithValue("@Availability", (short)(ushort)a_mo["Availability"]);
            sqlcmd.Parameters.AddWithValue("@Idx", (int)(uint)a_mo["Index"]);
            sqlcmd.Parameters.AddWithValue("@TimeOfLastReset", ResetTime);

			UnitAddData (sqlcmd);
		}	

		int RegisterCard (string a_ProductName, string a_Manufacturer, string a_ServiceName)
		{
			SqlCommand rcmd;
			SqlParameter paramO;
			SqlParameter retval;
			int card_id;

			rcmd = new SqlCommand ("dbo.spr_NIC", m_repository.SQLConnection);
			rcmd.CommandType = CommandType.StoredProcedure;

			retval = new SqlParameter ("retvalue", SqlDbType.Int);
			retval.Direction = ParameterDirection.ReturnValue;
			rcmd.Parameters.Add (retval);
            rcmd.Parameters.AddWithValue ("@ProductName", a_ProductName);
            rcmd.Parameters.AddWithValue ("@Manufacturer", a_Manufacturer);
            rcmd.Parameters.AddWithValue ("@ServiceName", a_ServiceName);
            paramO = rcmd.Parameters.AddWithValue ("@card_id", 0);
			paramO.Direction = ParameterDirection.Output;

			rcmd.ExecuteNonQuery ();
			try 
			{
				card_id = (int)paramO.Value;
			}
			catch (SqlException sqlex)
			{
				ChangeStatus (sqlex);
                throw (new StorageErrorException (CollectorError.StorSyntaxErrorReaderSP, sqlex.Number, "dbo.spr_NIC"));
			}

			return card_id;
		}

		short GetAdapterTypeID (string a_AdapterType)
		{
			short id = -1;

            SqlCommand command = new SqlCommand ("Select AdapterTypeID From dbo.d_AdapterType Where AdapterType=@AdapterType ",
                m_repository.SQLConnection);
            command.Parameters.AddWithValue ("@AdapterType", a_AdapterType);

			try
			{
                id = (short)command.ExecuteScalar ();
			}
			catch (NullReferenceException) 
			{
				ChangeStatus ("Unknown NIC type: "+a_AdapterType, StatusEventType.WARNING);
			}

			return id;
		}

		void StoreNicConfig (ManagementObject a_mo)
		{
            bool IPEnabled = false,
                IPXEnabled = false;
			int	TcpipNetbiosOptions = 0xffff;


            IPEnabled = (bool)a_mo["IPEnabled"];

			if (IPEnabled)
			{
                try
                {
                    IPXEnabled = (bool)a_mo["IPXEnabled"];
                }
                catch (NullReferenceException) { /*Not implemented on all platforms*/}
                
                try
				{
					TcpipNetbiosOptions = (int)(uint)a_mo["TcpipNetbiosOptions"];
				}
                catch (NullReferenceException) {/*Not implemented on all platforms*/}

                SqlCommand sqlcmd = new SqlCommand ();
                sqlcmd.CommandText =
@"Insert dbo.c_NICconfig (run_id,srv_id,Idx,DHCPEnabled,IPFilterSecurityEnabled,IPXEnabled,TcpipNetbiosOptions) 
Values (@run_id,@srv_id,@Idx,@DHCPEnabled,@IPFilterSecurityEnabled,@IPXEnabled,@TcpipNetbiosOptions) ";
                sqlcmd.Parameters.AddWithValue ("@run_id", m_rd.run_id);
                sqlcmd.Parameters.AddWithValue ("@srv_id", m_rd.srv_id);
                sqlcmd.Parameters.AddWithValue ("@Idx", (int)(uint)a_mo["Index"]);
                sqlcmd.Parameters.AddWithValue ("@DHCPEnabled", (bool)a_mo["DHCPEnabled"]);
                sqlcmd.Parameters.AddWithValue ("@IPFilterSecurityEnabled", (bool)a_mo["IPFilterSecurityEnabled"]);
                sqlcmd.Parameters.AddWithValue ("@IPXEnabled", IPXEnabled);
                sqlcmd.Parameters.AddWithValue ("@TcpipNetbiosOptions", TcpipNetbiosOptions);

                UnitAddData (sqlcmd);
			}
		}

		void StoreDiskDrive (ManagementObject a_mo)
		{
			string InterfaceType,
				Model,
				MediaType = String.Empty;
            short InterfaceTypeID = 0,
                SCSILogicalUnit = 0,
                SCSIPort = 0,
                SCSITargetId = 0;
			int ModelID,
				Partitions = -1,
                SCSIbus = 0;



			try
			{
				MediaType = (string)a_mo["MediaType"];
			}
            catch (NullReferenceException) {/*Not implemented on all platforms*/}
            if (!(0 == string.Compare (MediaType, "Fixed hard disk media", StringComparison.Ordinal)
                || 0 == string.Compare (MediaType, "Fixed/thard disk media", StringComparison.Ordinal)
                || 0 == string.Compare (MediaType, "External hard disk media", StringComparison.Ordinal)))
            {
                return;
            }

			try 
			{
				Partitions = (int)(uint)a_mo["Partitions"];
			}
            catch (NullReferenceException) {/*Not implemented on all platforms*/}

			InterfaceType = (string)a_mo["InterfaceType"];
            switch (InterfaceType)
            {
                case "SCSI": InterfaceTypeID = 1;
                    break;
                case "IDE": InterfaceTypeID = 2;
                    break;
                case "USB": InterfaceTypeID = 3;
                    break;
                default: InterfaceTypeID = 0;
                    ChangeStatus ("Unknown Disk Interface type: " + InterfaceType, StatusEventType.WARNING);
                    break;
            }

			Model = (string)a_mo["Model"];
            if (String.IsNullOrEmpty (Model))
            {
                return;
            }

			ModelID = RegisterDiskModel (Model);

            if (InterfaceTypeID == 1 || InterfaceTypeID == 2)
            {
                SCSIbus = (int)(uint)a_mo["SCSIbus"];
                SCSILogicalUnit = (short)(ushort)a_mo["SCSILogicalUnit"];
                SCSIPort = (short)(ushort)a_mo["SCSIPort"];
                SCSITargetId = (short)(ushort)a_mo["SCSITargetId"];
            }

            SqlCommand sqlcmd = new SqlCommand ();
            sqlcmd.CommandText =
@"Insert dbo.c_DiskDrive (run_id,srv_id,Idx,InterfaceTypeID,ModelID,Partitions,SCSIbus,SCSILogicalUnit,SCSIPort,SCSITargetId,Size,Status) 
Values (@run_id,@srv_id,@Idx,@InterfaceTypeID,@ModelID,@Partitions,@SCSIbus,@SCSILogicalUnit,@SCSIPort,@SCSITargetId,@Size,@Status) ";
            sqlcmd.Parameters.AddWithValue ("@run_id", m_rd.run_id);
            sqlcmd.Parameters.AddWithValue ("@srv_id", m_rd.srv_id);
            sqlcmd.Parameters.AddWithValue ("@Idx", (int)(uint)a_mo["Index"]);
            sqlcmd.Parameters.AddWithValue ("@InterfaceTypeID", InterfaceTypeID);
            sqlcmd.Parameters.AddWithValue ("@ModelID", ModelID);
            sqlcmd.Parameters.AddWithValue ("@Partitions", Partitions);
            sqlcmd.Parameters.AddWithValue ("@SCSIbus", SCSIbus);
            sqlcmd.Parameters.AddWithValue ("@SCSILogicalUnit", SCSILogicalUnit);
            sqlcmd.Parameters.AddWithValue ("@SCSIPort", SCSIPort);
            sqlcmd.Parameters.AddWithValue ("@SCSITargetId", SCSITargetId);
            sqlcmd.Parameters.AddWithValue ("@Size", (long)(ulong)a_mo["Size"]);
            sqlcmd.Parameters.AddWithValue ("@Status", (string)a_mo["Status"]);

			UnitAddData (sqlcmd);
		}

		int RegisterDiskModel (string a_Model)
		{
			SqlCommand rcmd;
			SqlParameter param,
				paramO;
			SqlParameter retval;
			int ModelID;


			rcmd = new SqlCommand ("dbo.spr_Disk", m_repository.SQLConnection);
			rcmd.CommandType = CommandType.StoredProcedure;

			retval = new SqlParameter ("retvalue", SqlDbType.Int);
			retval.Direction = ParameterDirection.ReturnValue;
			rcmd.Parameters.Add (retval);
			param = new SqlParameter ("@Model", SqlDbType.VarChar);
			param.Value = a_Model;
			rcmd.Parameters.Add (param);
			paramO = new SqlParameter ("@ModelID", SqlDbType.Int);
			paramO.Direction = ParameterDirection.Output;
			rcmd.Parameters.Add (paramO);

			rcmd.ExecuteNonQuery ();
			try 
			{
				ModelID = (int)paramO.Value;
			}
			catch (SqlException sqlex)
			{
				ChangeStatus (sqlex);
				throw (new StorageErrorException (CollectorError.StorSyntaxErrorReaderSP,sqlex.Number,"dbo.spr_DiskModel"));
			}

			return ModelID;
		}

		void StoreDiskPartition (ManagementObject a_mo)
		{
            string DeviceID = Convert.ToString(a_mo["DeviceID"]);
            Int32 Access = Convert.ToInt32(a_mo["Access"]);
            Int32 Availability = Convert.ToInt32(a_mo["Availability"]);
            Int64 BlockSize = Convert.ToInt64(a_mo["BlockSize"]);
            bool Bootable = Convert.ToBoolean(a_mo["Bootable"]);
            bool BootPartition = Convert.ToBoolean(a_mo["BootPartition"]);
            string Caption = Convert.ToString(a_mo["Caption"]);
            Int32 ConfigManagerErrorCode = Convert.ToInt32(a_mo["ConfigManagerErrorCode"]);
            bool ConfigManagerUserConfig = Convert.ToBoolean(a_mo["ConfigManagerUserConfig"]);
            string CreationClassName = Convert.ToString(a_mo["CreationClassName"]);
            string Description = Convert.ToString(a_mo["Description"]);
            Int32 DiskIndex = Convert.ToInt32(a_mo["DiskIndex"]);
            bool ErrorCleared = Convert.ToBoolean(a_mo["ErrorCleared"]);
            string ErrorDescription = Convert.ToString(a_mo["ErrorDescription"]);
            string ErrorMethodology = Convert.ToString(a_mo["ErrorMethodology"]);
            Int32 HiddenSectors = Convert.ToInt32(a_mo["HiddenSectors"]);
            Int32 Idx = Convert.ToInt32(a_mo["Index"]);
            DateTime InstallDate = DateTime.Parse("1/1/1900");
            if (Convert.ToDateTime(a_mo["InstallDate"]) != DateTime.MinValue)
            {
                InstallDate = Convert.ToDateTime(a_mo["InstallDate"]);
            }
            Int32 LastErrorCode = Convert.ToInt32(a_mo["LastErrorCode"]);
            string Name = Convert.ToString(a_mo["Name"]);
            Int64 NumberOfBlocks = Convert.ToInt64(a_mo["NumberOfBlocks"]);
            string PNPDeviceID = Convert.ToString(a_mo["PNPDeviceID"]);
            Int32 PowerManagementCapabilities = Convert.ToInt32(a_mo["PowerManagementCapabilities"]);
            bool PowerManagementSupported = Convert.ToBoolean(a_mo["PowerManagementSupported"]);
            bool PrimaryPartition = Convert.ToBoolean(a_mo["PrimaryPartition"]);
            string Purpose = Convert.ToString(a_mo["Purpose"]);
            bool RewritePartition = Convert.ToBoolean(a_mo["RewritePartition"]);
            Int64 Size = Convert.ToInt64(a_mo["Size"]);
            Int64 StartingOffset = Convert.ToInt64(a_mo["StartingOffset"]);
            string Status = Convert.ToString(a_mo["Status"]);
            Int32 StatusInfo = Convert.ToInt32(a_mo["StatusInfo"]);
            string SystemCreationClassName = Convert.ToString(a_mo["SystemCreationClassName"]);
            string SystemName = Convert.ToString(a_mo["SystemName"]);
            string Type = Convert.ToString(a_mo["Type"]);

            SqlCommand sqlcmd = new SqlCommand();
            sqlcmd.CommandText = @"INSERT INTO [dbo].[c_DiskPartition]
                                       ([run_id]
                                       ,[srv_id]
                                       ,[DeviceID]
                                       ,[Access]
                                       ,[Availability]
                                       ,[BlockSize]
                                       ,[Bootable]
                                       ,[BootPartition]
                                       ,[Caption]
                                       ,[ConfigManagerErrorCode]
                                       ,[ConfigManagerUserConfig]
                                       ,[CreationClassName]
                                       ,[Description]
                                       ,[DiskIndex]
                                       ,[ErrorCleared]
                                       ,[ErrorDescription]
                                       ,[ErrorMethodology]
                                       ,[HiddenSectors]
                                       ,[Idx]
                                       ,[InstallDate]
                                       ,[LastErrorCode]
                                       ,[Name]
                                       ,[NumberOfBlocks]
                                       ,[PNPDeviceID]
                                       ,[PowerManagementCapabilities]
                                       ,[PowerManagementSupported]
                                       ,[PrimaryPartition]
                                       ,[Purpose]
                                       ,[RewritePartition]
                                       ,[Size]
                                       ,[StartingOffset]
                                       ,[Status]
                                       ,[StatusInfo]
                                       ,[SystemCreationClassName]
                                       ,[SystemName]
                                       ,[Type])
                                 VALUES
                                       (@run_id,
			                            @srv_id,
			                            @DeviceID,
			                            @Access,
			                            @Availability,
			                            @BlockSize,
			                            @Bootable,
			                            @BootPartition,
			                            @Caption,
			                            @ConfigManagerErrorCode,
			                            @ConfigManagerUserConfig,
			                            @CreationClassName,
			                            @Description,
			                            @DiskIndex,
			                            @ErrorCleared,
			                            @ErrorDescription,
			                            @ErrorMethodology,
			                            @HiddenSectors,
			                            @Idx,
			                            @InstallDate,
			                            @LastErrorCode,
			                            @Name,
			                            @NumberOfBlocks,
			                            @PNPDeviceID,
			                            @PowerManagementCapabilities,
			                            @PowerManagementSupported,
			                            @PrimaryPartition,
			                            @Purpose,
			                            @RewritePartition,
			                            @Size,
			                            @StartingOffset,
			                            @Status,
			                            @StatusInfo,
			                            @SystemCreationClassName,
			                            @SystemName,
			                            @Type	)";
            sqlcmd.Parameters.AddWithValue("run_id", m_rd.run_id);
            sqlcmd.Parameters.AddWithValue("srv_id", m_rd.srv_id);
            sqlcmd.Parameters.AddWithValue("DeviceID", DeviceID);
            sqlcmd.Parameters.AddWithValue("Access", Access);
            sqlcmd.Parameters.AddWithValue("Availability", Availability);
            sqlcmd.Parameters.AddWithValue("BlockSize", BlockSize);
            sqlcmd.Parameters.AddWithValue("Bootable", Bootable);
            sqlcmd.Parameters.AddWithValue("BootPartition", BootPartition);
            sqlcmd.Parameters.AddWithValue("Caption", Caption);
            sqlcmd.Parameters.AddWithValue("ConfigManagerErrorCode", ConfigManagerErrorCode);
            sqlcmd.Parameters.AddWithValue("ConfigManagerUserConfig", ConfigManagerUserConfig);
            sqlcmd.Parameters.AddWithValue("CreationClassName", CreationClassName);
            sqlcmd.Parameters.AddWithValue("Description", Description);
            sqlcmd.Parameters.AddWithValue("DiskIndex", DiskIndex);
            sqlcmd.Parameters.AddWithValue("ErrorCleared", ErrorCleared);
            sqlcmd.Parameters.AddWithValue("ErrorDescription", ErrorDescription);
            sqlcmd.Parameters.AddWithValue("ErrorMethodology", ErrorMethodology);
            sqlcmd.Parameters.AddWithValue("HiddenSectors", HiddenSectors);
            sqlcmd.Parameters.AddWithValue("Idx", Idx);
            sqlcmd.Parameters.AddWithValue("InstallDate", InstallDate);
            sqlcmd.Parameters.AddWithValue("LastErrorCode", LastErrorCode);
            sqlcmd.Parameters.AddWithValue("Name", Name);
            sqlcmd.Parameters.AddWithValue("NumberOfBlocks", NumberOfBlocks);
            sqlcmd.Parameters.AddWithValue("PNPDeviceID", PNPDeviceID);
            sqlcmd.Parameters.AddWithValue("PowerManagementCapabilities", PowerManagementCapabilities);
            sqlcmd.Parameters.AddWithValue("PowerManagementSupported", PowerManagementSupported);
            sqlcmd.Parameters.AddWithValue("PrimaryPartition", PrimaryPartition);
            sqlcmd.Parameters.AddWithValue("Purpose", Purpose);
            sqlcmd.Parameters.AddWithValue("RewritePartition", RewritePartition);
            sqlcmd.Parameters.AddWithValue("Size", Size);
            sqlcmd.Parameters.AddWithValue("StartingOffset", StartingOffset);
            sqlcmd.Parameters.AddWithValue("Status", Status);
            sqlcmd.Parameters.AddWithValue("StatusInfo", StatusInfo);
            sqlcmd.Parameters.AddWithValue("SystemCreationClassName", SystemCreationClassName);
            sqlcmd.Parameters.AddWithValue("SystemName", SystemName);
            sqlcmd.Parameters.AddWithValue("Type", Type);

            UnitAddData(sqlcmd);

		}

		void StoreLogicalDisk (ManagementObject a_mo)
		{
            Int32 Access = Convert.ToInt32(a_mo["Access"]);
            Int32   Availability = Convert.ToInt32(a_mo["Availability"]);
            Int64   BlockSize = Convert.ToInt64(a_mo["BlockSize"]);
            string Caption = Convert.ToString(a_mo["Caption"]);
            bool Compressed = Convert.ToBoolean(a_mo["Compressed"]);
            Int32 ConfigManagerErrorCode = Convert.ToInt32(a_mo["ConfigManagerErrorCode"]);
            bool ConfigManagerUserConfig = Convert.ToBoolean(a_mo["ConfigManagerUserConfig"]);
            string CreationClassName = Convert.ToString(a_mo["CreationClassName"]);
            string   Description = Convert.ToString(a_mo["Description"]);
            string   DeviceID = Convert.ToString(a_mo["DeviceID"]);
            Int32 DriveType = Convert.ToInt32(a_mo["DriveType"]);
            bool ErrorCleared = Convert.ToBoolean(a_mo["ErrorCleared"]);
            string   ErrorDescription = Convert.ToString(a_mo["ErrorDescription"]);
            string   ErrorMethodology = Convert.ToString(a_mo["ErrorMethodology"]);
            string   FileSystem = Convert.ToString(a_mo["FileSystem"]);
            Int64 FreeSpace = Convert.ToInt64(a_mo["FreeSpace"]);
            DateTime InstallDate = DateTime.Parse("1/1/1900");
            if (Convert.ToDateTime(a_mo["InstallDate"]) != DateTime.MinValue)
            {
                InstallDate = Convert.ToDateTime(a_mo["InstallDate"]);
            }
            Int32 LastErrorCode = Convert.ToInt32(a_mo["LastErrorCode"]);
            Int32 MaximumComponentLength = Convert.ToInt32(a_mo["MaximumComponentLength"]);
            Int32 MediaType = Convert.ToInt32(a_mo["MediaType"]);
            string   Name = Convert.ToString(a_mo["Name"]);
            Int64 NumberOfBlocks = Convert.ToInt64(a_mo["NumberOfBlocks"]);
            string   PNPDeviceID = Convert.ToString(a_mo["PNPDeviceID"]);
            Int16 PowerManagementCapabilities = Convert.ToInt16(a_mo["PowerManagementCapabilities"]);
            bool PowerManagementSupported = Convert.ToBoolean(a_mo["PowerManagementSupported"]);
            string   ProviderName = Convert.ToString(a_mo["ProviderName"]);
            string   Purpose = Convert.ToString(a_mo["Purpose"]);
            bool QuotasDisabled = Convert.ToBoolean(a_mo["QuotasDisabled"]);
            bool QuotasIncomplete = Convert.ToBoolean(a_mo["QuotasIncomplete"]);
            bool QuotasRebuilding = Convert.ToBoolean(a_mo["QuotasRebuilding"]);
            Int64 Size = Convert.ToInt64(a_mo["Size"]);
            string   Status = Convert.ToString(a_mo["Status"]);
            Int16 StatusInfo = Convert.ToInt16(a_mo["StatusInfo"]);
            bool SupportsDiskQuotas = Convert.ToBoolean(a_mo["SupportsDiskQuotas"]);
            bool SupportsFileBasedCompression = Convert.ToBoolean(a_mo["SupportsFileBasedCompression"]);
            string   SystemCreationClassName = Convert.ToString(a_mo["SystemCreationClassName"]);
            string   SystemName = Convert.ToString(a_mo["SystemName"]);
            bool  VolumeDirty = Convert.ToBoolean(a_mo["VolumeDirty"]);
            string   VolumeName = Convert.ToString(a_mo["VolumeName"]);
            string   VolumeSerialNumber = Convert.ToString(a_mo["VolumeSerialNumber"]);

            SqlCommand sqlcmd = new SqlCommand();
            sqlcmd.CommandText = @"INSERT INTO [dbo].[c_LogicalDisk]
                                       ([run_id]
                                       ,[srv_id]
                                       ,[DeviceID]
                                       ,[Access]
                                       ,[Availability]
                                       ,[BlockSize]
                                       ,[Caption]
                                       ,[Compressed]
                                       ,[ConfigManagerErrorCode]
                                       ,[ConfigManagerUserConfig]
                                       ,[CreationClassName]
                                       ,[Description]
                                       ,[DriveType]
                                       ,[ErrorCleared]
                                       ,[ErrorDescription]
                                       ,[ErrorMethodology]
                                       ,[FileSystem]
                                       ,[FreeSpace]
                                       ,[InstallDate]
                                       ,[LastErrorCode]
                                       ,[MaximumComponentLength]
                                       ,[MediaType]
                                       ,[Name]
                                       ,[NumberOfBlocks]
                                       ,[PNPDeviceID]
                                       ,[PowerManagementCapabilities]
                                       ,[PowerManagementSupported]
                                       ,[ProviderName]
                                       ,[Purpose]
                                       ,[QuotasDisabled]
                                       ,[QuotasIncomplete]
                                       ,[QuotasRebuilding]
                                       ,[Size]
                                       ,[Status]
                                       ,[StatusInfo]
                                       ,[SupportsDiskQuotas]
                                       ,[SupportsFileBasedCompression]
                                       ,[SystemCreationClassName]
                                       ,[SystemName]
                                       ,[VolumeDirty]
                                       ,[VolumeName]
                                       ,[VolumeSerialNumber])
                                 VALUES
                                       (@run_id,
                                       @srv_id,
                                       @DeviceID,
                                       @Access,
                                       @Availability,
                                       @BlockSize,
                                       @Caption,
                                       @Compressed,
                                       @ConfigManagerErrorCode,
                                       @ConfigManagerUserConfig,
                                       @CreationClassName,
                                       @Description,
                                       @DriveType,
                                       @ErrorCleared,
                                       @ErrorDescription,
                                       @ErrorMethodology,
                                       @FileSystem,
                                       @FreeSpace,
                                       @InstallDate,
                                       @LastErrorCode,
                                       @MaximumComponentLength,
                                       @MediaType,
                                       @Name,
                                       @NumberOfBlocks,
                                       @PNPDeviceID,
                                       @PowerManagementCapabilities,
                                       @PowerManagementSupported,
                                       @ProviderName,
                                       @Purpose,
                                       @QuotasDisabled,
                                       @QuotasIncomplete,
                                       @QuotasRebuilding,
                                       @Size,
                                       @Status,
                                       @StatusInfo,
                                       @SupportsDiskQuotas,
                                       @SupportsFileBasedCompression,
                                       @SystemCreationClassName,
                                       @SystemName,
                                       @VolumeDirty,
                                       @VolumeName,
                                       @VolumeSerialNumber)";
            sqlcmd.Parameters.AddWithValue("@run_id", m_rd.run_id);
            sqlcmd.Parameters.AddWithValue("@srv_id", m_rd.srv_id);
            sqlcmd.Parameters.AddWithValue("@DeviceID", DeviceID);
            sqlcmd.Parameters.AddWithValue("@Access", Access);
            sqlcmd.Parameters.AddWithValue("@Availability", Availability);
            sqlcmd.Parameters.AddWithValue("@BlockSize", BlockSize);
            sqlcmd.Parameters.AddWithValue("@Caption", Caption);
            sqlcmd.Parameters.AddWithValue("@Compressed", Compressed);
            sqlcmd.Parameters.AddWithValue("@ConfigManagerErrorCode", ConfigManagerErrorCode);
            sqlcmd.Parameters.AddWithValue("@ConfigManagerUserConfig", ConfigManagerUserConfig);
            sqlcmd.Parameters.AddWithValue("@CreationClassName", CreationClassName);
            sqlcmd.Parameters.AddWithValue("@Description", Description);
            sqlcmd.Parameters.AddWithValue("@DriveType", DriveType);
            sqlcmd.Parameters.AddWithValue("@ErrorCleared", ErrorCleared);
            sqlcmd.Parameters.AddWithValue("@ErrorDescription", ErrorDescription);
            sqlcmd.Parameters.AddWithValue("@ErrorMethodology", ErrorMethodology);
            sqlcmd.Parameters.AddWithValue("@FileSystem", FileSystem);
            sqlcmd.Parameters.AddWithValue("@FreeSpace", FreeSpace);
            sqlcmd.Parameters.AddWithValue("@InstallDate", InstallDate);
            sqlcmd.Parameters.AddWithValue("@LastErrorCode", LastErrorCode);
            sqlcmd.Parameters.AddWithValue("@MaximumComponentLength", MaximumComponentLength);
            sqlcmd.Parameters.AddWithValue("@MediaType", MediaType);
            sqlcmd.Parameters.AddWithValue("@Name", Name);
            sqlcmd.Parameters.AddWithValue("@NumberOfBlocks", NumberOfBlocks);
            sqlcmd.Parameters.AddWithValue("@PNPDeviceID", PNPDeviceID);
            sqlcmd.Parameters.AddWithValue("@PowerManagementCapabilities", PowerManagementCapabilities);
            sqlcmd.Parameters.AddWithValue("@PowerManagementSupported", PowerManagementSupported);
            sqlcmd.Parameters.AddWithValue("@ProviderName", ProviderName);
            sqlcmd.Parameters.AddWithValue("@Purpose", Purpose);
            sqlcmd.Parameters.AddWithValue("@QuotasDisabled", QuotasDisabled);
            sqlcmd.Parameters.AddWithValue("@QuotasIncomplete", QuotasIncomplete);
            sqlcmd.Parameters.AddWithValue("@QuotasRebuilding", QuotasRebuilding);
            sqlcmd.Parameters.AddWithValue("@Size", Size);
            sqlcmd.Parameters.AddWithValue("@Status", Status);
            sqlcmd.Parameters.AddWithValue("@StatusInfo", StatusInfo);
            sqlcmd.Parameters.AddWithValue("@SupportsDiskQuotas", SupportsDiskQuotas);
            sqlcmd.Parameters.AddWithValue("@SupportsFileBasedCompression", SupportsFileBasedCompression);
            sqlcmd.Parameters.AddWithValue("@SystemCreationClassName", SystemCreationClassName);
            sqlcmd.Parameters.AddWithValue("@SystemName", SystemName);
            sqlcmd.Parameters.AddWithValue("@VolumeDirty", VolumeDirty);
            sqlcmd.Parameters.AddWithValue("@VolumeName", VolumeName);
            sqlcmd.Parameters.AddWithValue("@VolumeSerialNumber", VolumeSerialNumber);

            UnitAddData(sqlcmd);
		}

		void StoreLogFileInfo (ManagementObject a_mo)
		{
			short type;

			string LogFileName = a_mo["LogFileName"].ToString();

            // type goes directly to the collection table c_wmi_logfile
            // no associate dictionary table exists - Reports rely on numbers
			switch (LogFileName)
			{
				case "System":
					type = 0;
					break;
				case "Application":
					type = 1;
					break;
				case "Security":
					type = 2;
					break;
				default:
					ChangeStatus ("Skipping unknown Log File: "+LogFileName, StatusEventType.INFO);
					return;
			}

            SqlCommand sqlcmd = new SqlCommand ();
            sqlcmd.CommandText =
@"Insert dbo.c_wmi_logfile (run_id,srv_id,type,FileSize,MaxFileSize,OverwriteOutDated,Name,OverwritePolicy,Status) 
Values (@run_id,@srv_id,@type,@FileSize,@MaxFileSize,@OverwriteOutDated,@Name,@OverwritePolicy,@Status) ";
            sqlcmd.Parameters.AddWithValue ("@run_id", m_rd.run_id);
            sqlcmd.Parameters.AddWithValue ("@srv_id", m_rd.srv_id);
            sqlcmd.Parameters.AddWithValue ("@type", type);
            sqlcmd.Parameters.AddWithValue ("@FileSize", (long)(ulong)a_mo["FileSize"]);
            sqlcmd.Parameters.AddWithValue ("@MaxFileSize", (long)(uint)a_mo["MaxFileSize"]);
            sqlcmd.Parameters.AddWithValue ("@OverwriteOutDated", (int)(uint)a_mo["OverwriteOutDated"]);
            sqlcmd.Parameters.AddWithValue ("@Name", (string)a_mo["Name"]);
            sqlcmd.Parameters.AddWithValue ("@OverwritePolicy", (string)a_mo["OverWritePolicy"]);
            sqlcmd.Parameters.AddWithValue ("@Status", (string)a_mo["Status"]);

			UnitAddData (sqlcmd);
		}

		void StoreProcess (ManagementObject a_mo)
		{
			DateTime CreationDate = MIN_DATE;

			try
			{
				CreationDate = MakeDate ((string)a_mo["CreationDate"]);
			}
			catch (NullReferenceException) {/*Not implemented on all platforms*/}

            SqlCommand sqlcmd = new SqlCommand ();
            sqlcmd.CommandText = "dbo.spri_task";
            sqlcmd.CommandType = CommandType.StoredProcedure;
            sqlcmd.Parameters.AddWithValue ("@run_id", m_rd.run_id);
            sqlcmd.Parameters.AddWithValue ("@srv_id", m_rd.srv_id);
            sqlcmd.Parameters.AddWithValue ("@name", (string)a_mo["Name"]);
            sqlcmd.Parameters.AddWithValue ("@pid", (int)(uint)a_mo["ProcessId"]);
            sqlcmd.Parameters.AddWithValue ("@sid", (int)(uint)a_mo["SessionId"]);

			if (CreationDate != MIN_DATE)
			{
                sqlcmd.Parameters.AddWithValue ("@crdate", CreationDate);
            }
			
			UnitAddData (sqlcmd);
		}

		void StoreProduct (ManagementObject a_mo)
		{
			try
			{
				string sInstallDate = (string)a_mo["InstallDate"];
                DateTime InstallDate = MakeDate (sInstallDate);

                string name = (string)a_mo["Name"];
                if (String.IsNullOrEmpty(name))
                {
                    // try getting Caption instead 
                    name = (string)a_mo["Caption"];
                    if (String.IsNullOrEmpty(name))
                    {
                        // no point recording if there is no name
                        return;
                    }
                }

                SqlCommand sqlcmd = new SqlCommand ();
                sqlcmd.CommandText = "dbo.spri_product";
                sqlcmd.CommandType = CommandType.StoredProcedure;
                sqlcmd.Parameters.AddWithValue ("@run_id", m_rd.run_id);
                sqlcmd.Parameters.AddWithValue ("@srv_id", m_rd.srv_id);
                sqlcmd.Parameters.AddWithValue ("@name", name);
                sqlcmd.Parameters.AddWithValue ("@vendor", (string)a_mo["Vendor"] ?? String.Empty);
                sqlcmd.Parameters.AddWithValue ("@crdate", InstallDate);
                sqlcmd.Parameters.AddWithValue ("@state", (short)a_mo["InstallState"]);
                sqlcmd.Parameters.AddWithValue ("@ver", (string)a_mo["Version"] ?? String.Empty);

				UnitAddData (sqlcmd);
			}
			catch (NullReferenceException)
            {/*Not implemented on all platforms*/
			}
			catch (Exception ex)
			{
				ChangeStatus (ex.GetType ().ToString ()+": "+ex.Message, StatusEventType.DEBUG);
				ChangeStatus (ex.StackTrace, StatusEventType.STACK_TRACE);
				throw ex;
			}
		}

		void StoreService (ManagementObject a_mo)
		{
			try
			{
                SqlCommand sqlcmd = new SqlCommand ();
                sqlcmd.CommandText = "dbo.spri_service";
                sqlcmd.CommandType = CommandType.StoredProcedure;
                sqlcmd.Parameters.AddWithValue ("@run_id", m_rd.run_id);
                sqlcmd.Parameters.AddWithValue ("@srv_id", m_rd.srv_id);
                sqlcmd.Parameters.AddWithValue ("@name", (string)a_mo["Name"]);
                sqlcmd.Parameters.AddWithValue ("@DisplayName", (string)a_mo["DisplayName"]);
                sqlcmd.Parameters.AddWithValue ("@pid", (int)(uint)a_mo["ProcessId"]);
                sqlcmd.Parameters.AddWithValue ("@mode", (string)a_mo["StartMode"]);
                sqlcmd.Parameters.AddWithValue ("@account", (string)a_mo["StartName"] ?? String.Empty);
                sqlcmd.Parameters.AddWithValue ("@state", (string)a_mo["State"]);

				UnitAddData (sqlcmd);
			}
			catch (NullReferenceException)
            {/*Not implemented on all platforms*/
			}
			catch (Exception ex)
			{
				ChangeStatus (ex.GetType ().ToString ()+": "+ex.Message, StatusEventType.DEBUG);
				ChangeStatus (ex.StackTrace, StatusEventType.STACK_TRACE);
				throw ex;
			}
		}

		#endregion
	}
}
